// Copyright (c) 2020-2022 百小僧, Baiqian Co.,Ltd.
// Furion is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//             https://gitee.com/dotnetchina/Furion/blob/master/LICENSE
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;


namespace Anno.Repository
{
    [Anno.Loader.NotInInject]
    /// <summary>
    /// 非泛型 SqlSugar 仓储
    /// </summary>
    public partial class SqlSugarRepository : ISqlSugarRepository
    {
        /// <summary>
        /// 服务提供器
        /// </summary>
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serviceProvider">服务提供器</param>
        /// <param name="db"></param>
        public SqlSugarRepository(IServiceProvider serviceProvider
            , ISqlSugarClient db)
        {
            _serviceProvider = serviceProvider;
            DynamicContext = Context = (SqlSugarClient)db;
            Ado = db.Ado;

        }
        public SqlSugar.DbType DbType { get => Context.CurrentConnectionConfig.DbType; }
        public ITenant Tenant { get => Context.AsTenant(); }
        /// <summary>
        /// 数据库上下文
        /// </summary>
        public virtual SqlSugarClient Context { get; }

        /// <summary>
        /// 动态数据库上下文
        /// </summary>
        public virtual dynamic DynamicContext { get; }

        /// <summary>
        /// 原生 Ado 对象
        /// </summary>
        public virtual IAdo Ado { get; }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual ISqlSugarRepository<TEntity> Change<TEntity>()
            where TEntity : class, new()
        {
            return _serviceProvider.GetService<ISqlSugarRepository<TEntity>>();
        }

        public bool IsAnyConnection(dynamic configId)
        {
            return Context.IsAnyConnection(configId);
        }

        public void ChangeDatabase(dynamic configId)
        {
            if (Context.CurrentConnectionConfig.ConfigId != Convert.ToString(configId))
                Context.ChangeDatabase(configId);
        }

        public void ChangeDatabase(Func<SqlSugar.ConnectionConfig, bool> changeExpression)
        {
            Context.ChangeDatabase(changeExpression);
        }

        #region ExecutePro
        protected static Dictionary<string, Dictionary<string, SqlSugar.SugarParameter>> dicDbParameter
            = new Dictionary<string, Dictionary<string, SqlSugar.SugarParameter>>(StringComparer.OrdinalIgnoreCase);
        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual bool ExecutePro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            if (_sql.Sql.IsNullOrEmpty_()) return false;
            var sql = GetSqlEntityPro(_sql, paras);
            //Context.Ado.UseStoredProcedure().GetDataTable(sql.Sql, sql.Parameters?.ToArray());
            var ret = this.Context.Ado.UseStoredProcedure().ExecuteCommand(sql.Sql, sql.Parameters?.ToArray());
            return ret >= 0;
        }
        /// <summary>
        /// 存储过程返回数据集
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual DataSet GetDataSetPro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            if (_sql.Sql.IsNullOrEmpty_()) return new DataSet();
            var sql = GetSqlEntityPro(_sql, paras);
            var ret = this.Context.Ado.UseStoredProcedure().GetDataSetAll(sql.Sql, sql.Parameters?.ToArray());
            return ret;
        }
        /// <summary>
        /// 存储过程返回DataTable
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual DataTable GetDataTablePro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            if (_sql.Sql.IsNullOrEmpty_()) return new DataTable();
            var sql = GetSqlEntityPro(_sql, paras);
            var ret = this.Context.Ado.UseStoredProcedure().GetDataTable(sql.Sql, sql.Parameters?.ToArray());
            return ret;
        }

        public virtual DataSet QueryDataSet(SqlEntity _sql)
        {
            if (_sql.IsNullOrEmpty_() || _sql.Sql.IsNullOrEmpty_()) return new DataSet();
            if (_sql.CommandType == CommandType.StoredProcedure)
                return this.Context.Ado.UseStoredProcedure().GetDataSetAll(_sql.Sql, _sql.Parameters?.ToArray());
            else
                return this.Context.Ado.GetDataSetAll(_sql.Sql, _sql.Parameters?.ToArray());
        }
        public virtual DataTable QueryDataTable(SqlEntity _sql)
        {
            if (_sql.IsNullOrEmpty_() || _sql.Sql.IsNullOrEmpty_()) return new DataTable();
            if (_sql.CommandType == CommandType.StoredProcedure)
                return this.Context.Ado.UseStoredProcedure().GetDataTable(_sql.Sql, _sql.Parameters?.ToArray());
            else
                return this.Context.Ado.GetDataTable(_sql.Sql, _sql.Parameters?.ToArray());
        }
        /// <summary>
        /// 生成存储过程参数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual SqlEntity GetSqlEntityPro(SqlEntity sql, object obj)
        {
            var paras = obj.ToDictionary();
            return GetSqlEntityPro(sql, paras);
        }
        /// <summary>
        /// 生成存储过程参数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public SqlEntity GetSqlEntityPro(SqlEntity sql, Dictionary<string, object> paras)
        {
            if (sql.Sql.IsNullOrEmpty_()) return sql;
            sql.CommandType = CommandType.StoredProcedure;
            string dbName = this.Context.CurrentConnectionConfig.ConfigId;
            if (!dicDbParameter.TryGetValue(dbName + sql.Sql, out Dictionary<string, SqlSugar.SugarParameter> dbparas))
            {
                dbparas = new Dictionary<string, SqlSugar.SugarParameter>(StringComparer.OrdinalIgnoreCase);
                if (this.DbType == SqlSugar.DbType.SqlServer)
                {
                    var dstype = this.Context.Ado.GetDataSetAll($"exec sp_help  '{sql.Sql}'");
                    if (dstype != null && dstype.Tables.Count > 1)
                    {
                        foreach (DataRow dr in dstype.Tables[1].Rows)
                        {
                            var ParameterName = dr.GetColumnValue("Parameter_name").NullToStr().Replace("@", "");
                            var dbp = new SqlSugar.SugarParameter(ParameterName, null);
                            dbp.TypeName = dr.GetColumnValue("Type").NullToStr();

                            dbparas[dbp.ParameterName] = dbp;
                        }
                    }
                }
                else if (this.DbType == SqlSugar.DbType.Oracle)
                {
                    var dstype = this.Context.Ado.GetDataTable($"select t.object_name,t.argument_name,t.data_type,t.in_out from all_arguments t where t.object_name='{sql.Sql.ToUpper()}' order by t.POSITION");
                    if (dstype != null && dstype.Rows.Count > 0)
                    {
                        foreach (DataRow dr in dstype.Rows)
                        {
                            var ParameterName = dr.GetColumnValue("ARGUMENT_NAME").NullToStr().Replace(":", "");
                            var dbp = new SqlSugar.SugarParameter(ParameterName, null);
                            dbp.TypeName = dr.GetColumnValue("DATA_TYPE").NullToStr();
                            var in_out = dr.GetColumnValue("IN_OUT").NullToStr();
                            dbp.Direction = in_out == "IN" ? System.Data.ParameterDirection.Input : System.Data.ParameterDirection.Output;
                            dbparas[dbp.ParameterName] = dbp;
                        }
                    }
                }
                dicDbParameter[dbName + sql.Sql] = dbparas;
            }
            if (dbparas?.Count > 0)
            {
                if (this.DbType == SqlSugar.DbType.Oracle)
                {
                    foreach (var dbp in dbparas.Values)
                    {
                        if (dbp.TypeName == "REF CURSOR")
                        {
                            sql.AddParameter(dbp.ParameterName, "", System.Data.ParameterDirection.Output, true);
                        }
                        else
                        {
                            if (!paras.TryGetValue(dbp.ParameterName, out object val))
                                if (dbp.ParameterName.StartsWith("v_", StringComparison.OrdinalIgnoreCase)
                                    && !paras.TryGetValue(dbp.ParameterName.Substring(2), out val))
                                    val = null;
                            sql.AddParameter(dbp.ParameterName, val, dbp.Direction);
                        }
                    }
                }
                else
                {
                    foreach (var dbp in dbparas.Values)
                    {
                        if (!paras.TryGetValue(dbp.ParameterName, out var val))
                            val = null;
                        sql.AddParameter(dbp.ParameterName, val, dbp.Direction);
                    }
                }
            }
            return sql;
        }
        #endregion
    }
    [Anno.Loader.NotInInject]
    /// <summary>
    /// SqlSugar 仓储实现类
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public partial class SqlSugarRepository<TEntity> : ISqlSugarRepository<TEntity>
    where TEntity : class, new()
    {
        /// <summary>
        /// 非泛型 SqlSugar 仓储
        /// </summary>
        private readonly ISqlSugarRepository _sqlSugarRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugarRepository"></param>
        public SqlSugarRepository(ISqlSugarRepository sqlSugarRepository)
        {
            _sqlSugarRepository = sqlSugarRepository;

            //数据库上下文根据实体切换,业务分库(使用环境例如微服务)
            var entityType = typeof(TEntity);
            if (entityType.IsDefined(typeof(SqlSugar.TenantAttribute), false))
            {
                var tenantAttribute = entityType.GetCustomAttribute<SqlSugar.TenantAttribute>(false)!;
                _sqlSugarRepository.ChangeDatabase(tenantAttribute.configId);
            }
            //else
            //{
            //    _sqlSugarRepository.ChangeDatabase(Loader.IocLoader.Resolve<ConnectionStringsOptions>().DefaultDbNumber);
            //}
            DynamicContext = Context = sqlSugarRepository.Context;
            Ado = sqlSugarRepository.Ado;
        }
        public SqlSugar.DbType DbType { get => Context.CurrentConnectionConfig.DbType; }
        public ITenant Tenant { get => Context.AsTenant(); }
        /// <summary>
        /// 实体集合
        /// </summary>
        public virtual ISugarQueryable<TEntity> Entities => Context.Queryable<TEntity>();

        /// <summary>
        /// 数据库上下文
        /// </summary>
        public virtual SqlSugarClient Context { get; }

        /// <summary>
        /// 动态数据库上下文
        /// </summary>
        public virtual dynamic DynamicContext { get; }

        /// <summary>
        /// 原生 Ado 对象
        /// </summary>
        public virtual IAdo Ado { get; }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual ISqlSugarRepository<TChangeEntity> Change<TChangeEntity>()
            where TChangeEntity : class, new()
        {
            return _sqlSugarRepository.Change<TChangeEntity>();
        }
        public bool IsAnyConnection(dynamic configId)
        {
            return _sqlSugarRepository.IsAnyConnection(configId);
        }

        public void ChangeDatabase(dynamic configId)
        {
            _sqlSugarRepository.ChangeDatabase(configId);
        }

        public void ChangeDatabase(Func<SqlSugar.ConnectionConfig, bool> changeExpression)
        {
            _sqlSugarRepository.ChangeDatabase(changeExpression);
        }

        #region ExecutePro
        protected static Dictionary<string, Dictionary<string, SqlSugar.SugarParameter>> dicDbParameter
            = new Dictionary<string, Dictionary<string, SqlSugar.SugarParameter>>(StringComparer.OrdinalIgnoreCase);
        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual bool ExecutePro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            return _sqlSugarRepository.ExecutePro(_sql,paras);
        }
        /// <summary>
        /// 存储过程返回数据集
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual DataSet GetDataSetPro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            return _sqlSugarRepository.GetDataSetPro(_sql, paras);
        }
        /// <summary>
        /// 存储过程返回DataTable
        /// </summary>
        /// <param name="_sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public virtual DataTable GetDataTablePro(SqlEntity _sql, Dictionary<string, string> paras)
        {
            return _sqlSugarRepository.GetDataTablePro(_sql, paras);
        }

        public virtual DataSet QueryDataSet(SqlEntity _sql)
        {
            return _sqlSugarRepository.QueryDataSet(_sql);
        }
        public virtual DataTable QueryDataTable(SqlEntity _sql)
        {
            return _sqlSugarRepository.QueryDataTable(_sql);
        }
        /// <summary>
        /// 生成存储过程参数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual SqlEntity GetSqlEntityPro(SqlEntity sql, object obj)
        {
            return _sqlSugarRepository.GetSqlEntityPro(sql, obj);
        }
        /// <summary>
        /// 生成存储过程参数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public SqlEntity GetSqlEntityPro(SqlEntity sql, Dictionary<string, object> paras)
        {
            return _sqlSugarRepository.GetSqlEntityPro(sql, paras);
        }
        #endregion

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public int Count(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Count(whereExpression);
        }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<int> CountAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.CountAsync(whereExpression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public bool Any(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Any(whereExpression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.AnyAsync(whereExpression);
        }

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public TEntity Single(dynamic Id)
        {
            return Entities.InSingle(Id);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity Single(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Single(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.SingleAsync(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.First(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.FirstAsync(whereExpression);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public virtual List<TEntity> ToList()
        {
            return Entities.ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public virtual List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public virtual Task<List<TEntity>> ToListAsync()
        {
            return Entities.ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public virtual Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
        }
        #region Insert
        /// <summary>
        /// 新增一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Insert(TEntity entity)
        {
            return Context.Insertable(entity).ExecuteCommand();
        }
        public int Insert(TEntity entity, Expression<Func<TEntity, object>> iClumns = null, bool ignoreNull = true)
        {
            return Context.Insertable(entity).InsertColumns(iClumns).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommand();
        }
        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Insert(params TEntity[] entities)
        {
            return Context.Insertable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Insert(IEnumerable<TEntity> entities)
        {
            return Context.Insertable(entities.ToArray()).ExecuteCommand();
        }

        /// <summary>
        /// 新增一条记录返回自增Id
        /// </summary>
        /// <param name="insertObj"></param>
        /// <returns></returns>
        public virtual int InsertReturnIdentity(TEntity insertObj)
        {
            return Context.Insertable(insertObj).ExecuteReturnIdentity();
        }

        /// <summary>
        /// 新增一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(TEntity entity)
        {
            return Context.Insertable(entity).ExecuteCommandAsync();
        }
        public Task<int> InsertAsync(TEntity entity, Expression<Func<TEntity, object>> iClumns = null, bool ignoreNull = true)
        {
            return Context.Insertable(entity).InsertColumns(iClumns).IgnoreColumns(ignoreNullColumn: ignoreNull).ExecuteCommandAsync();
        }
        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(params TEntity[] entities)
        {
            return Context.Insertable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(IEnumerable<TEntity> entities)
        {
            return Context.Insertable(entities.ToArray()).ExecuteCommandAsync();
        }

        /// <summary>
        /// 新增一条记录返回自增Id
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<long> InsertReturnIdentityAsync(TEntity entity)
        {
            return await Context.Insertable(entity).ExecuteReturnBigIdentityAsync();
        }
#endregion
        #region Update
        /// <summary>
        /// 更新一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Update(TEntity entity)
        {
            return Context.Updateable(entity).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Update(params TEntity[] entities)
        {
            return Context.Updateable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Update(IEnumerable<TEntity> entities)
        {
            return Context.Updateable(entities.ToArray()).ExecuteCommand();
        }

        public virtual int Update(TEntity entity, bool ignoreNullColumns = false)
        {
            return Context.Updateable(entity).IgnoreColumns(ignoreNullColumns).ExecuteCommand();
        }

        public virtual int Update(TEntity entity, Expression<Func<TEntity, object>> expression, bool ignoreAllNull = false)
        {
            return Context.Updateable(entity).UpdateColumns(expression).IgnoreColumns(ignoreAllNull).ExecuteCommand();
        }

        /// <summary>
        /// 根据实体类更新指定列 eg：Update(dept, it => new { it.Status }, f => depts.Contains(f.DeptId));只更新Status列，条件是包含
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="expression"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual int Update(TEntity entity, Expression<Func<TEntity, object>> expression, Expression<Func<TEntity, bool>> where)
        {
            return Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();
        }

        public virtual int Update(SqlSugarClient client, TEntity entity, Expression<Func<TEntity, object>> expression, Expression<Func<TEntity, bool>> where)
        {
            return client.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();
        }
        /// <summary>
        /// 更新指定列 eg：Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ Update_time = DateTime.Now, Title = "通知标题" });
        /// </summary>
        /// <param name="where"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public int Update(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> columns)
        {
            return Context.Updateable<TEntity>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommand();
        }

        public virtual Task<int> UpdateAsync(TEntity entity, bool ignoreNullColumns = false)
        {
            return Context.Updateable(entity).IgnoreColumns(ignoreNullColumns).ExecuteCommandAsync();
        }

        public virtual Task<int> UpdateAsync(TEntity entity, Expression<Func<TEntity, object>> expression, bool ignoreAllNull = false)
        {
            return Context.Updateable(entity).UpdateColumns(expression).IgnoreColumns(ignoreAllNull).ExecuteCommandAsync();
        }

        /// <summary>
        /// 根据实体类更新指定列 eg：Update(dept, it => new { it.Status }, f => depts.Contains(f.DeptId));只更新Status列，条件是包含
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="expression"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(TEntity entity, Expression<Func<TEntity, object>> expression, Expression<Func<TEntity, bool>> where)
        {
            return Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommandAsync();
        }

        public virtual Task<int> UpdateAsync(SqlSugarClient client, TEntity entity, Expression<Func<TEntity, object>> expression, Expression<Func<TEntity, bool>> where)
        {
            return client.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommandAsync();
        }
        /// <summary>
        /// 更新指定列 eg：Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ Update_time = DateTime.Now, Title = "通知标题" });
        /// </summary>
        /// <param name="where"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> columns)
        {
            return Context.Updateable<TEntity>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommandAsync();
        }
        /// <summary>
        /// 更新一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(TEntity entity)
        {
            return Context.Updateable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(params TEntity[] entities)
        {
            return Context.Updateable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(IEnumerable<TEntity> entities)
        {
            return Context.Updateable(entities.ToArray()).ExecuteCommandAsync();
        }
        #endregion
        #region Delete
        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Delete(TEntity entity)
        {
            return Context.Deleteable(entity).ExecuteCommand();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual int Delete(object key)
        {
            return Context.Deleteable<TEntity>().In(key).ExecuteCommand();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual int Delete(params object[] keys)
        {
            return Context.Deleteable<TEntity>().In(keys).ExecuteCommand();
        }

        /// <summary>
        /// 自定义条件删除记录
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual int Delete(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Context.Deleteable<TEntity>().Where(whereExpression).ExecuteCommand();
        }
        public virtual int DeleteTable()
        {
            return Context.Deleteable<TEntity>().ExecuteCommand();
        }
        public virtual Task<int> DeleteTableAsync()
        {
            return Context.Deleteable<TEntity>().ExecuteCommandAsync();
        }
        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(TEntity entity)
        {
            return Context.Deleteable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(object key)
        {
            return Context.Deleteable<TEntity>().In(key).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(params object[] keys)
        {
            return Context.Deleteable<TEntity>().In(keys).ExecuteCommandAsync();
        }

        /// <summary>
        /// 自定义条件删除记录
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Context.Deleteable<TEntity>().Where(whereExpression).ExecuteCommandAsync();
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="client"></param>
        /// <param name="action">增删改查方法</param>
        /// <returns></returns>
        public DbResult<bool> UseTran(SqlSugarClient client, Action action)
        {
            try
            {
                var result = client.AsTenant().UseTran(() => action());
                return result;
            }
            catch (Exception ex)
            {
                client.AsTenant().RollbackTran();
                Console.WriteLine(ex.Message);
                throw;
            }
        }
        public DbResult<bool> UseTran(Action action)
        {
            return UseTran(Context, action);
        }
        public IStorageable<TEntity> Storageable(TEntity t)
        {
            return Context.Storageable<TEntity>(t);
        }
        public IStorageable<TEntity> Storageable(List<TEntity> t)
        {
            return Context.Storageable(t);
        }

        /// <summary>
        /// 根据表达式查询多条记录
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate);
        }

        /// <summary>
        /// 根据表达式查询多条记录
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> Where(bool condition, Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable().WhereIF(condition, predicate);
        }

        /// <summary>
        /// 构建查询分析器
        /// </summary>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> AsQueryable()
        {
            return Entities;
        }

        /// <summary>
        /// 构建查询分析器
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> AsQueryable(Expression<Func<TEntity, bool>> predicate)
        {
            return Entities.Where(predicate);
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <returns></returns>
        public virtual List<TEntity> AsEnumerable()
        {
            return AsQueryable().ToList();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual List<TEntity> AsEnumerable(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate).ToList();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <returns></returns>
        public virtual Task<List<TEntity>> AsAsyncEnumerable()
        {
            return AsQueryable().ToListAsync();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual Task<List<TEntity>> AsAsyncEnumerable(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate).ToListAsync();
        }


        public (List<TEntity>, int) QueryableToPage(Expression<Func<TEntity, bool>> expression, int pageIndex = 0, int pageSize = 10)
        {
            int totalNumber = 0;
            var list = Context.Queryable<TEntity>().Where(expression).ToPageList(pageIndex, pageSize, ref totalNumber);
            return (list, totalNumber);
        }

        public (List<TEntity>, int) QueryableToPage(Expression<Func<TEntity, bool>> expression, string order, int pageIndex = 0, int pageSize = 10)
        {
            int totalNumber = 0;
            var list = Context.Queryable<TEntity>().Where(expression).OrderBy(order).ToPageList(pageIndex, pageSize, ref totalNumber);
            return (list, totalNumber);
        }

        public (List<TEntity>, int) QueryableToPage(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderFiled, string orderBy, int pageIndex = 0, int pageSize = 10)
        {
            int totalNumber = 0;

            if (orderBy.Equals("DESC", StringComparison.OrdinalIgnoreCase))
            {
                var list = Context.Queryable<TEntity>().Where(expression).OrderBy(orderFiled, OrderByType.Desc).ToPageList(pageIndex, pageSize, ref totalNumber);
                return (list, totalNumber);
            }
            else
            {
                var list = Context.Queryable<TEntity>().Where(expression).OrderBy(orderFiled, OrderByType.Asc).ToPageList(pageIndex, pageSize, ref totalNumber);
                return (list, totalNumber);
            }
        }
        /// <summary>
        /// 根据条件查询分页数据
        /// </summary>
        /// <param name="where"></param>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<TEntity> GetPages(Expression<Func<TEntity, bool>> where, PagerInfo parm)
        {
            var source = Context.Queryable<TEntity>().Where(where);

            return source.ToPage(parm);
        }

        public PagedInfo<TEntity> GetPages(Expression<Func<TEntity, bool>> where, PagerInfo parm, Expression<Func<TEntity, object>> order, OrderByType orderEnum = OrderByType.Asc)
        {
            var source = Context.Queryable<TEntity>().Where(where).OrderByIF(orderEnum == OrderByType.Asc, order, OrderByType.Asc).OrderByIF(orderEnum == OrderByType.Desc, order, OrderByType.Desc);

            return source.ToPage(parm);
        }

        public PagedInfo<TEntity> GetPages(Expression<Func<TEntity, bool>> where, PagerInfo parm, Expression<Func<TEntity, object>> order, string orderByType)
        {
            return GetPages(where, parm, order, orderByType == "desc" ? OrderByType.Desc : OrderByType.Asc);
        }

        /// <summary>
        /// 查询所有数据(无分页,请慎用)
        /// </summary>
        /// <returns></returns>
        public List<TEntity> GetAll(bool useCache = false, int cacheSecond = 3600)
        {
            return Context.Queryable<TEntity>().WithCacheIF(useCache, cacheSecond).ToList();
        }

        /// <summary>
        /// 此方法不带output返回值
        /// var list = new List<SugarParameter>();
        /// list.Add(new SugarParameter(ParaName, ParaValue)); input
        /// </summary>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DataTable UseStoredProcedureToDataTable(string procedureName, List<SugarParameter> parameters)
        {
            return Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters);
        }

        /// <summary>
        /// 带output返回值
        /// var list = new List<SugarParameter>();
        /// list.Add(new SugarParameter(ParaName, ParaValue, true));  output
        /// list.Add(new SugarParameter(ParaName, ParaValue)); input
        /// </summary>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public (DataTable, List<SugarParameter>) UseStoredProcedureToTuple(string procedureName, List<SugarParameter> parameters)
        {
            var result = (Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters), parameters);
            return result;
        }
    }
}